package com.gusto.utils.semantic;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;

import com.hp.hpl.jena.query.Query;
import com.hp.hpl.jena.query.QueryExecution;
import com.hp.hpl.jena.query.QueryExecutionFactory;
import com.hp.hpl.jena.query.QueryFactory;
import com.hp.hpl.jena.query.QuerySolution;
import com.hp.hpl.jena.query.ResultSet;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelMaker;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.Statement;
import com.hp.hpl.jena.rdf.model.StmtIterator;
import com.hp.hpl.jena.util.FileManager;

public class SemanticUtils {
	
	private Logger log = Logger.getLogger(SemanticUtils.class);
	
	public void loadDataFromFile(ModelMaker modelMaker, String theModelName, String fileLocation) throws Exception {
		long start, stop;
		
		if ( ! modelMaker.hasModel(theModelName)) { 
			log.debug("No model named '" + theModelName + "', creating ...");
			modelMaker.createModel(theModelName);
			log.info("Model '" + theModelName + "' created");
		}
		else {
			log.debug("The model named '" + theModelName + "' exists");
		}
		
		Model theModel = modelMaker.openModel(theModelName, true);
		
		log.debug("Loading data into '" + theModelName + "' ...");
		start = System.currentTimeMillis();
		InputStream in = FileManager.get().open(fileLocation);
		theModel.read(in, "");
		stop = System.currentTimeMillis();
		log.info("Data loaded into '" + theModelName + "' in " + (stop - start) + " milliseconds");
		
		theModel.close();
	}
	
	public void removeData(ModelMaker modelMaker, String theModelName) throws Exception {
		if ( ! modelMaker.hasModel(theModelName)) { 
			log.error("Model '" + theModelName + "' doesn't exist, cannot remove data");
		}
		
		log.debug("The model named '" + theModelName + "' exists, removing data ...");
		Model theModel = modelMaker.openModel(theModelName, true);
		theModel.removeAll();
		log.info("Data removed from '" + theModelName + "'");
		theModel.close();
	}
	
	public void getResourceProperties(Model model, String resource, String property) {
		Resource r = model.getResource(resource);
		Property p = (property != null ? model.getProperty(property) : null);
		StmtIterator stmtI = model.listStatements(r, (Property)p, (RDFNode)null);
		
		stmtI = r.listProperties(p);
		while (stmtI.hasNext()) {
			Statement stmt = stmtI.nextStatement();
			System.out.println(stmt);
		}
	}
	
	public List<QuerySolution> sparqlQuery(Model model, String queryfile) {
		log.info("Executing query from '" + queryfile + "'");
		String queryString = getFileAsString(queryfile);
		return sparqlQueryString(model, queryString);
	}
	
	
	public List<QuerySolution> sparqlQueryString(Model model, String queryString) {
		long start, stop;
		log.debug("Query : \n" + queryString);
		
		start = System.currentTimeMillis();
		Query query = QueryFactory.create(queryString);
		QueryExecution qExec = QueryExecutionFactory.create(query, model);
		
		List<QuerySolution> solutions = new ArrayList<QuerySolution>();
		
		ResultSet rset = qExec.execSelect();
		while (rset.hasNext()) {
			QuerySolution sol = (QuerySolution)rset.next();
			System.out.println(sol);
			solutions.add(sol);
		}
		stop = System.currentTimeMillis();
		log.debug("Query executed in : " + (stop - start) + " milliseconds");
		return solutions;
	}
	
	
	private static String getFileAsString(String path){
		StringBuilder content = new StringBuilder();
		try{
			BufferedReader bf = new BufferedReader(new FileReader(path));
			String currentLine;
			while( (currentLine = bf.readLine()) != null ){
				content.append(currentLine + "\n");
			}
		} catch (IOException ioe){
			ioe.printStackTrace();
		}
		return content.toString();
	}

}
